package com.siyoumi.app.sys.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.siyoumi.app.entity.SysAddress;
import com.siyoumi.app.entity.WxUser;
import com.siyoumi.app.entity.WxUserInfo;
import com.siyoumi.app.feign.view_admin.SiyoumiFeign;
import com.siyoumi.app.service.SysAddressService;
import com.siyoumi.app.service.WxUserInfoService;
import com.siyoumi.app.service.WxUserService;
import com.siyoumi.app.sys.entity.AesKi;
import com.siyoumi.app.sys.service.WxApiService;
import com.siyoumi.app.sys.service.WxTokenService;
import com.siyoumi.app.sys.service.wxapi.ApiConfig;
import com.siyoumi.app.sys.service.wxapi.WxApiApp;
import com.siyoumi.app.sys.vo.LoginVo;
import com.siyoumi.app.sys.vo.VaWxUser;
import com.siyoumi.app.sys.vo.WxAppQrVo;
import com.siyoumi.component.XApp;
import com.siyoumi.component.XBean;
import com.siyoumi.component.XRedis;
import com.siyoumi.component.http.InputData;
import com.siyoumi.component.http.XHttpContext;
import com.siyoumi.config.SysConfig;
import com.siyoumi.entity.SysAccsuperConfig;
import com.siyoumi.exception.EnumSys;
import com.siyoumi.service.IWebService;
import com.siyoumi.service.SysAccsuperConfigService;
import com.siyoumi.util.XDate;
import com.siyoumi.util.XReturn;
import com.siyoumi.util.XStr;
import com.siyoumi.validator.XValidator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

//接口
@Slf4j
@Service
public class WxAppServiceImpl
        implements WxApiService, IWebService {
    @Override
    @Transactional
    public XReturn login(LoginVo vo) {
        XHttpContext.setX(vo.getX());

        SysAccsuperConfig entityConfig = XHttpContext.getXConfig(true);
        if (entityConfig == null) {
            return EnumSys.ERR_VAL.getR();
        }
        if (XStr.isNullOrEmpty(entityConfig.getAconfig_app_id())) {
            return EnumSys.MISS_VAL.getR("miss app_id");
        }
        if (!entityConfig.wxOpen()) {
            if (XStr.isNullOrEmpty(entityConfig.getAconfig_app_secret())) {
                return EnumSys.MISS_VAL.getR("miss app_secret");
            }
        }

        WxApiApp miniProgram = WxApiApp.getIns(entityConfig);
        if (entityConfig.wxOpenClient()) {
            SysAccsuperConfig entityConfigParent = SysAccsuperConfigService.getBean().getXConfigWxOpenParent(entityConfig.getX());
            ApiConfig apiConfigParent = new ApiConfig();
            apiConfigParent.setAppId(entityConfigParent.getAconfig_app_id());
            apiConfigParent.setAccessToken(WxTokenService.getBean(entityConfigParent).getAccessToken());
            miniProgram.getConfig().setParent(apiConfigParent);
        }

        XReturn r = miniProgram.getUserInfo(vo.getCode());
        if (r.err()) {
            return r;
        }

        String openid = r.getData("openid");
        String unionid = r.getData("unionid", "");
        //String session_key = r.getData("session_key");

        //更新用户
        WxUserService appWxUser = WxUserService.getBean();
        WxUser entityWxUser = appWxUser.getByOpenid(openid, false);

        //为了不更新所有字段，需要new
        WxUser entityWxUserUpdate = new WxUser();
        if (entityWxUser == null) {
            entityWxUserUpdate.setWxuser_id(openid);
        }
        entityWxUserUpdate.setWxuser_openid(openid);
        entityWxUserUpdate.setWxuser_x_id(entityConfig.getKey());

        //unionid
        if (XStr.hasAnyText(unionid)) {
            entityWxUserUpdate.setWxuser_unionid(unionid);
        }
        try {
            entityWxUser = appWxUser.saveOrUpdatePassEqualField(entityWxUser, entityWxUserUpdate);
        } catch (Exception ex) {
            log.error(ex.getMessage());
            ex.printStackTrace();
            XValidator.err(EnumSys.SYS.getR(ex.getMessage()));
        }

        //前端返回参数
        return loginReturnDataWx(entityWxUser, entityConfig);
    }

    @Override
    public XReturn loginSetOpenid(String token) {
        if (XStr.isNullOrEmpty(token)) {
            return EnumSys.MISS_VAL.getR("miss token");
        }

        XRedis.getBean().setEx(token, getOpenid(), 300);
        return XReturn.getR(0);
    }

    @Override
    public XReturn getPhone(String code) {
        if (XStr.isNullOrEmpty(code)) {
            return EnumSys.MISS_VAL.getR("miss code");
        }

        SysAccsuperConfig entityConfig = XHttpContext.getXConfig(true);
        WxApiApp app = WxApiApp.getIns(entityConfig);
        XReturn r = app.getUserPhone(code);
        if (r.ok()) {
            JSONObject entity = r.getData("phone_info");
            String phone = entity.getString("phoneNumber");

            AesKi aesKi = AesKi.of(entityConfig.getAconfig_token());

            JSONObject phoneInfo = new JSONObject();
            phoneInfo.put("phoneNumber", phone);
            phoneInfo.put("phoneNumberEnc", aesKi.encTxt(phone));

            r.setData("phone_info", phoneInfo);
        }

        return r;
    }


    @Override
    public XReturn userEdit(WxUserInfo entityWxUserInfo) {
        WxUserInfoService app = WxUserInfoService.getBean();
        WxUserInfo entity = app.getByOpenid(getOpenid());
        if (entity == null) {
            return EnumSys.ERR_VAL.getR("openid 异常");
        }


        InputData data = InputData.getIns();
        data.putAll(entityWxUserInfo.toMap());
        data.put("id", entity.getWinfo_id() + "");

        return app.saveEntity(data);
    }

    @Override
    public XReturn userUpdate(VaWxUser vo) {
        WxUserService appUser = WxUserService.getBean();
        WxUser entityWxUser = appUser.getByOpenid(getOpenid());

        WxUser entityUpdate = new WxUser();
        XBean.copyProperties(vo, entityUpdate);
        if (XStr.isNullOrEmpty(entityUpdate.getWxuser_phone())) {
            entityUpdate.setWxuser_phone(null);
        }
        entityUpdate.setWxuser_user_data_update_date(XDate.now());
        //
        entityWxUser = appUser.saveOrUpdatePassEqualField(entityWxUser, entityUpdate);
        //清缓存
        XReturn r = XReturn.getR(0);
        r.setData("entity_wxuser", entityWxUser);

        return r;
    }

    @Override
    public XReturn addressList(InputData inputData) {
        String compKw = inputData.input("compKw");

        SysAddressService appAddress = SysAddressService.getBean();
        QueryWrapper<SysAddress> query = appAddress.q();
        query.eq("addr_x_id", XHttpContext.getX())
                .eq("addr_openid", getOpenid())
                .orderByDesc("addr_def")
                .orderByAsc("addr_order");
        if (XStr.hasAnyText(compKw)) {
            //名称或者手机号
            query.and(q -> {
                q.like("addr_name", compKw)
                        .or().eq("addr_phone", compKw);
            });
        }
        Page<SysAddress> page = appAddress.page(inputData.getPageIndex(), inputData.getPageSize(), false);
        IPage<SysAddress> list = appAddress.get(page, query);

        XReturn r = XReturn.getR(0);
        r.setData("list", list);

        return r;
    }

    /**
     * 生成小程序码
     *
     * @param vo
     */
    public byte[] wxappQr(WxAppQrVo vo) {
        SysAccsuperConfig config;
        if ("x".equals(XHttpContext.get("x"))) {
            config = SiyoumiFeign.getBean().getConfigCenter();
        } else {
            config = SysAccsuperConfigService.getBean().getXConfig(XHttpContext.getX(), true);
        }

        WxApiApp miniProgram = WxApiApp.getIns(config);

        if (XStr.isNullOrEmpty(vo.getPath())) {
            vo.setPath("pages/login/login");
        }

        Map<String, Object> mapAppend = new HashMap<>();
        if (vo.getIs_hyaline() == 1) {
            mapAppend.put("is_hyaline", true);
        }

        if (SysConfig.getIns().isDev()) {
            log.debug("开发环境");
            vo.setEnv_version("develop");
        }
        mapAppend.put("check_path", false);
        if ("release".equals(vo.getEnv_version())) {
            log.debug("正式环境，路径不存在，会报错");
            mapAppend.put("check_path", true);
        }

        return miniProgram.getQrCodeUnlimited(vo.getScene(), vo.getPath(), mapAppend);
    }
}
